package com.shiguiwu.springmybatis.spring.aop.cglib;

import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.CallbackFilter;
import org.springframework.cglib.proxy.Dispatcher;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @description: dispatcher
 * @author: stone
 * @date: Created by 2021/5/18 20:38
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.aop.cglib
 */
public class DispatcherPlusTests {

    public static class UserService {
        public void add() {
            System.out.println("用户新增！！！");

        }

        public void update() {
            System.out.println("用户更新！！！");

        }
    }

    public interface IMethodInfo {
        //方法数量
        int methodCount();

        //方法名称列表
        List<String> methodNames();


    }

    public static class DefaultMethodInfo implements IMethodInfo {

        private Class<?> targetClass;



        public DefaultMethodInfo(Class<?> targetClass) {
            this.targetClass = targetClass;
        }

        @Override
        public int methodCount() {
            return targetClass.getDeclaredMethods().length;
        }

        @Override
        public List<String> methodNames() {
            return Arrays.stream(targetClass.getDeclaredMethods())
                    .map(Method::getName)
                    .collect(Collectors.toList());
        }
    }


    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        //代理父类
        enhancer.setSuperclass(UserService.class);

        //代理接口
        enhancer.setInterfaces(new Class[]{IMethodInfo.class});
        IMethodInfo iMethodInfo = new DefaultMethodInfo(UserService.class);

        MethodInterceptor methodInterceptor = new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                //调用父类的方法，也就是目标对象的方法
                return methodProxy.invokeSuper(o, objects);
            }

        };

        Dispatcher dispatcher = new Dispatcher() {
            @Override
            public Object loadObject() throws Exception {
                /*
                 * 用来处理代理对象中IMethodInfo接口中的所有方法
                 * 所以此处返回的为IMethodInfo类型的对象，
                 * 将由这个对象来处理代理对象中IMethodInfo接口中的所有方法
                 *
                 **/
                return iMethodInfo;
            }
        };

        enhancer.setCallbacks(new Callback[]{methodInterceptor, dispatcher});

        enhancer.setCallbackFilter(new CallbackFilter() {
            @Override
            public int accept(Method method) {
                //当方法在IMethodInfo中定义的时候，返回callbacks中的第二个元素
                return method.getDeclaringClass() == IMethodInfo.class ? 1 : 0;
            }
        });

        Object proxy = enhancer.create();
        UserService userService = (UserService) proxy;
        userService.add();

        IMethodInfo info = (IMethodInfo) proxy;
        System.out.println(info.methodCount());
        System.out.println(info.methodNames());
    }


}
